/*
//
//              INTEL CORPORATION PROPRIETARY INFORMATION
//  This software is supplied under the terms of a license  agreement or
//  nondisclosure agreement with Intel Corporation and may not be copied
//  or disclosed except in  accordance  with the terms of that agreement.
//    Copyright (c) 2007-2008 Intel Corporation. All Rights Reserved.
//
//
*/

#include "umc_defs.h"
#if defined(UMC_ENABLE_AVS_VIDEO_DECODER) || \
    defined(UMC_ENABLE_AVS_VIDEO_ENCODER)

#include "umc_avs_slice.h"
#include "umc_avs_context.h"

#include "umc_avs_sequence_header.h"
#include "umc_avs_picture_header.h"

namespace UMC
{

AVSSlice::AVSSlice(void)
{
    m_pPic = (AVSPicture *) 0;

    memset(&m_SlcHeader, 0, sizeof(m_SlcHeader));
    memset(&m_decCtx, 0, sizeof(m_decCtx));
    memset(&m_recCtx, 0, sizeof(m_recCtx));
    memset(&m_debCtx, 0, sizeof(m_debCtx));

} // AVSSlice::AVSSlice(void)

AVSSlice::~AVSSlice(void)
{
    m_pPic = (AVSPicture *) 0;

    memset(&m_SlcHeader, 0, sizeof(m_SlcHeader));
    memset(&m_decCtx, 0, sizeof(m_decCtx));
    memset(&m_recCtx, 0, sizeof(m_recCtx));
    memset(&m_debCtx, 0, sizeof(m_debCtx));

} // AVSSlice::~AVSSlice(void)

Status AVSSlice::InitCoeffsBuffer(size_t iMinPieceToWrite, Ipp32s iNumPieces)
{
    return m_coeffsBuf.Init(iMinPieceToWrite, iNumPieces);

} // Status AVSSlice::InitCoeffsBuffer(size_t iMinPieceToWrite, Ipp32s iNumPieces)

size_t AVSSlice::GetCoeffsBufferSize(void)
{
    return m_coeffsBuf.GetBufferSize();

} // size_t AVSSlice::GetCoeffsBufferSize(void)

Status AVSSlice::Reset(const AVS_SEQUENCE_HEADER *pSeqHeader,
                       const AVS_PICTURE_HEADER *pPicHeader)
{
    const AVS_SLICE_HEADER *pSlcHeader;
    Ipp32s MbYOffset;

    // check error(s)
    if ((NULL == pSeqHeader) ||
        (NULL == pPicHeader))
    {
        return UMC_ERR_NULL_PTR;
    }
    if ((VIDEO_SEQUENCE_START_CODE != pSeqHeader->video_sequence_start_code) &&
        (I_PICTURE_START_CODE != pPicHeader->picture_start_code) &&
        (BP_PICTURE_START_CODE != pPicHeader->picture_start_code))
    {
        return UMC_ERR_INVALID_PARAMS;
    }

    // reset pointers
    pSlcHeader = &m_SlcHeader;

    // initialize decoding context
    // NOTE: we can not set the decoding context to zeros,
    // because the bit stream context is already initialized.
    m_decCtx.MbFirst = pSlcHeader->first_mb;
    m_decCtx.MbIndex = pSlcHeader->first_mb;
    m_decCtx.MbWidth = (pSeqHeader->horizontal_size + 15) / 16;
    if (pPicHeader->picture_structure)
    {
        m_decCtx.MbHeight = (pSeqHeader->vertical_size + 15) / 16;
        MbYOffset = 0;
    }
    else
    {
        m_decCtx.MbHeight = ((pSeqHeader->vertical_size + 31) / 32);
        if (pSlcHeader->isSecondField)
            MbYOffset = m_decCtx.MbHeight;
        else
            MbYOffset = 0;
    }
    m_decCtx.MbLast = m_decCtx.MbWidth * m_decCtx.MbHeight;
    m_decCtx.FixedQP = (pPicHeader->fixed_picture_qp) ?
                       (pPicHeader->fixed_picture_qp) :
                       (pSlcHeader->fixed_slice_qp);
    m_decCtx.PreviousQP = (pPicHeader->fixed_picture_qp) ?
                          (pPicHeader->picture_qp) :
                          (pSlcHeader->slice_qp);

    switch (pSeqHeader->chroma_format)
    {
    case AVS_CHROMA_422_FORMAT:
        m_decCtx.iNumberOfBlocks = 8;
        break;

    default:
        m_decCtx.iNumberOfBlocks = 6;
        break;
    }
    m_decCtx.isSecondField = pSlcHeader->isSecondField;
    m_decCtx.m_pSlice = this;
    m_decCtx.m_pPicHeader = pPicHeader;
    m_decCtx.m_pSeqHeader = pSeqHeader;
    m_decCtx.m_pSlcHeader = pSlcHeader;
    if (0 == (pPicHeader->progressive_frame | pPicHeader->picture_structure))
    {
        m_decCtx.ScanType = 1;
    }
    m_decCtx.MbX = 0;
    m_decCtx.MbY = ((pSlcHeader->slice_vertical_position_extension << 7) |
                    (pSlcHeader->slice_vertical_position)) - MbYOffset;
    m_bDecVacant = true;

    // initialize reconstructing context
    memset(&m_recCtx, 0, sizeof(AVS_RECONSTRUCTING_CONTEXT));
    m_recCtx.MbFirst = pSlcHeader->first_mb;
    m_recCtx.MbIndex = pSlcHeader->first_mb;
    m_recCtx.MbWidth = m_decCtx.MbWidth;
    m_recCtx.MbHeight = m_decCtx.MbHeight;
    m_recCtx.MbLast = m_decCtx.MbLast;
    m_recCtx.FixedQP = m_decCtx.FixedQP;
    m_recCtx.PreviousQP = m_decCtx.PreviousQP;

    m_recCtx.iNumberOfBlocks = m_decCtx.iNumberOfBlocks;
    m_recCtx.isSecondField = m_decCtx.isSecondField;
    m_recCtx.m_pSlice = this;
    m_recCtx.m_pPicHeader = pPicHeader;
    m_recCtx.m_pSeqHeader = pSeqHeader;
    m_recCtx.m_pSlcHeader = pSlcHeader;
    m_recCtx.MbX = 0;
    m_recCtx.MbY = m_decCtx.MbY;
    m_bRecVacant = true;

    // initialize deblocking context
    memset(&m_debCtx, 0, sizeof(AVS_DEBLOCKING_CONTEXT));
    if (pPicHeader->loop_filter_disable)
    {
        m_debCtx.MbIndex = m_decCtx.MbLast;
        m_debCtx.MbLast = m_decCtx.MbLast;
    }
    else
    {
        m_debCtx.MbFirst = pSlcHeader->first_mb;
        m_debCtx.MbIndex = pSlcHeader->first_mb;
        m_debCtx.MbWidth = m_decCtx.MbWidth;
        m_debCtx.MbHeight = m_decCtx.MbHeight;
        m_debCtx.MbLast = m_decCtx.MbLast;

        m_debCtx.iNumberOfBlocks = m_decCtx.iNumberOfBlocks;
        m_debCtx.isSecondField = m_decCtx.isSecondField;
        m_debCtx.m_pSlice = this;
        m_debCtx.m_pPicHeader = pPicHeader;
        m_debCtx.m_pSeqHeader = pSeqHeader;
        m_debCtx.m_pSlcHeader = pSlcHeader;
        m_debCtx.MbX = 0;
        m_debCtx.MbY = m_decCtx.MbY;
    }
    m_bDebVacant = true;

    m_bError = false;

    return UMC_OK;

} // Status AVSSlice::Reset(const AVS_SEQUENCE_HEADER *pSeqHeader,

} // namespace UMC

#endif // defined(UMC_ENABLE_AVS_VIDEO_DECODER) ||
